package com.zhongwang.business.util;

import com.zhongwang.business.constant.Constant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 对象比较工具类
 *
 * @author China.sgl
 * @date 2019/8/7 15:47
 */
public class BeanUtil {

  /**
   * 比罗属性，返回值不同的字符串
   *
   * @param before
   * @param after
   * @param ignoreProperties
   * @return
   */
  public static String compare(Object before, Object after, String... ignoreProperties) {
    StringBuilder sb = new StringBuilder();
    final BeanWrapper beforeWrapper = new BeanWrapperImpl(before);
    PropertyDescriptor[] beforePds = beforeWrapper.getPropertyDescriptors();
    List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;
    for (PropertyDescriptor beforePd : beforePds) {
      if (ignoreList == null || !ignoreList.contains(beforePd.getName())) {
        try {
          PropertyDescriptor afterPd = new PropertyDescriptor(beforePd.getName(), after.getClass());
          Method beforeMethod = beforePd.getReadMethod();
          Method afterMethod = afterPd.getReadMethod();
          Object beforeValue = beforeMethod.invoke(before);
          Object afterValue = afterMethod.invoke(after);
          if (beforeValue != null
              && afterValue != null
              && !beforeValue.toString().equals(afterValue.toString())
              && Constant.FIELD_NAME.get(beforePd.getName()) != null) {
            sb.append(Constant.FIELD_NAME.get(beforePd.getName()))
                .append("：【")
                .append(beforeValue)
                .append("】 -> 【")
                .append(afterValue)
                .append("】<br>");
          }
        } catch (Exception e) {
          continue;
        }
      }
    }
    if (sb.toString().length() == 0) {
      sb.append("-");
    }
    return sb.toString();
  }

  public static String compare(Object before, Object after) {
    return compare(before, after, null);
    /*StringBuilder sb = new StringBuilder();
    try {
        Class clazz = before.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
            Method getMethod = pd.getReadMethod();
            Object obj1 = getMethod.invoke(before);
            Object obj2 = getMethod.invoke(after);
            String s1 = obj1 == null ? "" : obj1.toString();
            String s2 = obj2 == null ? "" : obj2.toString();
            if (obj1 != null && obj2 != null && !s1.equals(s2) && Constant.FIELD_NAME.get(field.getName()) != null) {
                sb.append(Constant.FIELD_NAME.get(field.getName()))
                        .append("：【")
                        .append(s1)
                        .append("】 -> 【")
                        .append(s2)
                        .append("】<br>");
            }
        }
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
    if (sb.toString().length() == 0) {
        sb.append("-");
    }
    return sb.toString();*/
  }

  /**
   * 获取需要忽略的属性
   *
   * @param source
   * @return
   */
  public static String[] getNullPropertyNames(Object source) {
    final BeanWrapper src = new BeanWrapperImpl(source);
    PropertyDescriptor[] pds = src.getPropertyDescriptors();

    Set<String> emptyNames = new HashSet<>();
    for (PropertyDescriptor pd : pds) {
      Object srcValue = src.getPropertyValue(pd.getName());
      if (srcValue == null) {
        emptyNames.add(pd.getName());
      }
    }
    String[] result = new String[emptyNames.size()];
    return emptyNames.toArray(result);
  }

  /**
   * 复制对象，并排除空属性
   *
   * @param source
   * @param target
   */
  public static void copy(Object source, Object target) {
    BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
  }
  /**
   * @methodName: cloneTo
   * @description: 对象深层拷贝
   * @param: src
   * @return： T
   * @exception：
   * @author： 徐一贺 tel:18941916590
   * @leader： 陈欣 tel:18104194240
   * @date： 2021/3/29 14:35
   * @office: 智能控制设计科
   * @research institute： 智能控制设计所
   * @department： 机械设计院
   * @company: 辽宁忠旺机械设备制造有限公司
   * @group： 忠旺集团
   * @version: 1.0
   */
  public static <T> T cloneTo(T src) throws RuntimeException {
    ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
    ObjectOutputStream out = null;
    ObjectInputStream in = null;
    T dist = null;
    try {
      out = new ObjectOutputStream(memoryBuffer);
      out.writeObject(src);
      out.flush();
      in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
      dist = (T) in.readObject();
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (out != null) {
        try {
          out.close();
          out = null;
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
      if (in != null) {
        try {
          in.close();
          in = null;
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    }
    return dist;
  }
}
